package com.xiyu.service.service.nurse;

import com.xiyu.service.util.entity.EntityUtils;
import com.xiyu.service.model.nurse.plan.NursePlan;
import com.xiyu.service.model.nurse.plan.NursePlanDetail;
import com.xiyu.service.model.nurse.plan.NursePlanDraft;
import com.xiyu.service.model.nurse.plan.NursePlanProps;
import com.xiyu.service.repository.nurse.plan.NursePlanDetailRepository;
import com.xiyu.service.repository.nurse.plan.NursePlanRepository;
import com.xiyu.service.vo.nurse.nursePlan.NursePlanPageOutput;
import com.xiyu.service.vo.nurse.nursePlan.NursePlanPageInput;
import com.xiyu.service.vo.nurse.nursePlan.NursePlanGetOutput;
import com.xiyu.service.vo.nurse.nursePlan.NursePlanUpdateInput;
import com.xiyu.service.vo.nurse.nursePlan.NursePlanCreateInput;
import org.babyfish.jimmer.DraftObjects;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.nurse.NursePlanConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.nurse.NursePlanErrorCode.*;

/**
 * 护理计划 Service 实现类
 */
@Service
@Validated
public class NursePlanServiceImpl implements NursePlanService {

    @Resource
    NursePlanRepository nursePlanRepository;

    @Resource
    NursePlanDetailRepository nursePlanDetailRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(NursePlanCreateInput inputVO) {
        Optional<NursePlan> opOldPlan = nursePlanRepository.findFirstByPlanName(inputVO.getPlanName());
        if(opOldPlan.isPresent()){
            throw exception(NURSE_PLAN_EXISTS);
        }
        NursePlan newPlan = NursePlanConvert.INSTANCE.createInputConvert(inputVO);
        newPlan = nursePlanRepository.insert(newPlan);
        return newPlan.id();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(NursePlanUpdateInput inputVO) {
        Optional<NursePlan> opExistsPlan = nursePlanRepository.findFirstByPlanNameAndIdNot(inputVO.getPlanName(), inputVO.getId());
        if(opExistsPlan.isPresent() ){
            throw exception(NURSE_PLAN_EXISTS);
        }
        Optional<NursePlan> opOldPlan = nursePlanRepository.findById(inputVO.getId());
        if(!opOldPlan.isPresent()){
            throw exception(NURSE_PLAN_NOT_EXISTS);
        }
        for(NursePlanUpdateInput.detail detail:  inputVO.getDetails()){
            if(Objects.equals(detail.getOperateType(), "new")){
                NursePlanDetail newDetail = NursePlanConvert.INSTANCE.updateDetailInputConvert(detail);
                nursePlanDetailRepository.insert(newDetail);
            }else if(Objects.equals(detail.getOperateType(), "delete")){
                nursePlanDetailRepository.deleteById(detail.getId());
            }else{
                NursePlanDetail updateDetail = NursePlanConvert.INSTANCE.updateDetailInputConvert(detail);
                Optional<NursePlanDetail> opOldDetail = nursePlanDetailRepository.findById(updateDetail.id());
                if(!opOldDetail.isPresent()){
                    throw exception(NURSE_PLAN_DETAIL_NOT_EXISTS);
                }
                if (!EntityUtils.isEquals(opOldDetail.get(), updateDetail))
                    nursePlanDetailRepository.update(updateDetail);
            }
        }

        NursePlan updatePlan = NursePlanConvert.INSTANCE.updateInputConvert(inputVO);
        updatePlan = NursePlanDraft.$.produce(updatePlan, draft -> {
            DraftObjects.unload(draft, NursePlanProps.DETAILS);
        });
        nursePlanRepository.update(updatePlan);
        return true;
    }

    @Override
    public NursePlanGetOutput get(Long id) {
        Optional<NursePlan> opPlan = nursePlanRepository.getById(id);
        if(!opPlan.isPresent()){
            throw exception(NURSE_PLAN_NOT_EXISTS);
        }
        return NursePlanConvert.INSTANCE.getOutputConvert(opPlan.get());
    }

    @Override
    public PageResult<NursePlanPageOutput> page(NursePlanPageInput inputVO) {
        Page<NursePlan> pagePlan = nursePlanRepository.pageQuery(inputVO);
        List<NursePlanPageOutput> listPlan =NursePlanConvert.INSTANCE.pagePageOutputConvert(pagePlan.getRows());
        return new PageResult<>(listPlan, pagePlan.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleted(Long id) {
        Optional<NursePlan> opPlan = nursePlanRepository.findById(id);
        if(!opPlan.isPresent()){
            throw exception(NURSE_PLAN_NOT_EXISTS);
        }
        nursePlanRepository.deleteById(id);
        return true;
    }

}
